package uy.org.softtech.cssuite.web.controladores;

import static org.springframework.util.Assert.notNull;
import static uy.org.softtech.cssuite.helpers.HelperSeguridad.usuarioActual;

import java.util.Locale;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.context.annotation.Configuration;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import uy.org.softtech.cssuite.core.Comando;
import uy.org.softtech.cssuite.core.Controlador;
import uy.org.softtech.cssuite.entidad.usuario.Usuario;
import uy.org.softtech.cssuite.excepciones.EntidadNoEncontradaException;
import uy.org.softtech.cssuite.servicios.ServiciosUsuarios;
import uy.org.softtech.cssuite.web.modelo.ModeloPerfil;

/**
 * Controlador encargado de manejar el perfil del usuario logueado.
 * 
 * @author fabian.lobo
 */
@Configuration
@Controller("controlador-perfil")
@ManagedResource(
	objectName = "cssuite:type=Controlador,name=ControladorPerfil", 
	description = "Controlador encargado de manejar el perfil del usuario logueado.",
	log = true, logFile = "jmx.log", currencyTimeLimit = 15,
	persistPolicy = "OnUpdate", persistPeriod = 200
)
public class ControladorPerfil extends Controlador {
	
	private Logger log = Logger.getLogger(getClass());
	
	// Comandos
	@Resource(name = "comando-perfil")
	private Comando comandoPerfil;
	
	// Servicios
	@Resource(name = "servicios-usuarios" )
	private ServiciosUsuarios serviciosUsuarios;
	
	/**
	 * Método para verificar que todos los parámetros han sido seteados correctamente.
	 * 
	 * @author fabian.lobo
	 */
	@PostConstruct
	public void inicializacion(){
		super.inicializacion();
		
		notNull(comandoPerfil(), "La propiedad [comandoCredenciales] de [" + getClass().getName() + "] no ha sido establecida.");
		notNull(serviciosUsuarios(), "La propiedad [serviciosUsuarios] de [" + getClass().getName() + "] no ha sido establecida.");
		
		log.info("Controlador encargado de manejar el perfil del usuario logueado ha sido inicializado.");
	}

	/* 
	 * ---------------------------------------
	 * ----------   CONFIGURACION   ----------
	 * ---------------------------------------
	 */
	
	/**
	 * Retorna la página de perfil.
	 * 
	 * @author fabian.lobo
	 */
	@RequestMapping(method = RequestMethod.GET, value = "perfil.do")
	@Secured(value = {"ROLE_AUTENTICADO"})
	public String perfil(@ModelAttribute(value = "modeloPerfil") ModeloPerfil modelo){
		modelo.setAccion(Accion.PERFIL);
		
		Long id = usuarioActual().getId();
		try {
			modelo.inicializaModelo(serviciosUsuarios().buscarUsuario(id));
		} catch (EntidadNoEncontradaException e) {
			//Nunca debería pasar
			log.error(e);
			modelo.inicializaModelo(usuarioActual());
		}
		
		return "perfil";
	}
	
	/**
	 * Procesa la solicitud de actualización de perfil.
	 * 
	 * @author fabian.lobo
	 */
	@RequestMapping(method = RequestMethod.POST, value = "perfil.do")
	@Secured(value = {"ROLE_AUTENTICADO"})
	public ModelAndView procesaActualizacionPerfil(Locale locale, @ModelAttribute(value = "modeloPerfil") ModeloPerfil modelo, BindingResult errores) {
		ModelAndView respuesta = new ModelAndView("perfil");
		
		//Seteamos en el modelo los valores de los campos deshabilitados ya que no vienen como parte del request
		try {
			Usuario usuario = serviciosUsuarios().buscarUsuario(modelo.getId());
			modelo.setUsuario(usuario.getUsuario());
			modelo.setUltimoLogin(usuario.convierteUltimoLogin());
			modelo.setRol(usuario.getRol().getNombre());
		} catch (EntidadNoEncontradaException e) {
			log.equals(e);
			registrarErrorGeneral(errores, locale);
			return respuesta;
		}
		
		modelo.setLocale(locale);
		try {
			boolean ejecutado = comandoPerfil().ejecutar(modelo, errores);
			if(ejecutado) {
				//Actualizamos los datos del objeto Principal en la autenticación (sólo Primer nombre, Segundo nombre y Apellido)
				usuarioActual().setApellido(modelo.getApellido());
				usuarioActual().setPrimerNombre(modelo.getPrimerNombre());
				usuarioActual().setSegundoNombre(modelo.getSegundoNombre());
				
				//Mostramos mensaje al usuario
				String mensaje = fuenteMensajes().getMessage("mensaje.datosActualizados", null, "Los datos han sido actualizados correctamente.", locale);
				mostrarMensajeInformacion(respuesta, mensaje, false, null);
			}
		} catch (Exception e) {
			log.error(e);
			registrarErrorGeneral(errores, locale);
		}
		return respuesta;
	}
	
	/*
	 *  GETTERS
	 */
	public Comando comandoPerfil() {
		return comandoPerfil;
	}
	public ServiciosUsuarios serviciosUsuarios() {
		return serviciosUsuarios;
	}
}
